package com.feature50.makeover.utils;

import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.geom.Point2D;

/**
 * A collection of handy Java2D routines.
 */
public class PaintUtils {
    public static final int GRAY_BUFFER_HEIGHT = 6;

    /**
     * Paints a multi-stop gradient on the passed graphics, using the passed compoen
     *
     * @param g
     * @param gradientStart
     * @param gradientStop
     * @param paintStart
     * @param paintSize
     * @param gradientColors
     * @param gradientDistribution
     */
    public static void paintGradient(Graphics2D g, Point2D gradientStart, Point2D gradientStop,
                                     Point paintStart, Dimension paintSize,
                                     Color[] gradientColors, float[] gradientDistribution) {
        if (gradientColors == null) return;

        int width = paintSize.width;
        int height = paintSize.height;

        int xstart = (gradientStart == null) ? 0 : (int) (gradientStart.getX() * width);
        int xstop = (gradientStop == null) ? width - 1 : (int) (gradientStop.getX() * width);
        int ystart = (gradientStart == null) ? 0 : (int) (gradientStart.getY() * height);
        int ystop = (gradientStop == null) ? 0 : (int) (gradientStop.getY() * height);

        float[] distribution = gradientDistribution;
        if (distribution == null) {
            distribution = new float[gradientColors.length];
            float multiplier = 1.0f / (gradientColors.length - 1);
            for (int i = 0; i < distribution.length; i++) {
                distribution[i] = 1.0f * multiplier * i;
            }
        }

        g.setPaint(new LinearGradientPaint(xstart, ystart, xstop, ystop, distribution, gradientColors));
        g.fillRect(paintStart.x, paintStart.y, width, height);
    }

    /**
     *
     * @param g
     * @param size
     * @param image
     * @param horizontalPosition a percentage from 0 to 1 along y axis
     * @param verticalPosition a percentage from 0 to 1 along x axis
     * @param horizontalRepeat
     * @param verticalRepeat
     */
    public static void paintImage(Graphics2D g, Dimension size, BufferedImage image,
                                  float horizontalPosition, float verticalPosition,
                                  boolean horizontalRepeat, boolean verticalRepeat) {
        if (image == null) return;

        int width = size.width;
        int height = size.height;

        int w = image.getWidth();
        int h = image.getHeight();

        int x = (int) ((float) width * horizontalPosition);
        int y = (int) ((float) height * verticalPosition);

        int dx = (int) ((float) w * horizontalPosition);
        int dy = (int) ((float) h * verticalPosition);

        x -= dx;
        y -= dy;

        if ((horizontalRepeat) && (verticalRepeat)) {
            int tx = x, ty = y;
            while (tx > 0) tx -= w;
            while (ty > 0) ty -= h;

            int py = ty;
            while (tx < width) {
                while (py < height) {
                    g.drawImage(image, tx, py, null);
                    py += h;
                }
                tx += w;
                py = ty;
            }
        } else if (horizontalRepeat) {
            int tx = x;
            while (tx > 0) tx -= w;

            while (tx < width) {
                g.drawImage(image, tx, y, null);
                tx += w;
            }
        } else if (verticalRepeat) {
            int ty = y;
            while (ty > 0) ty -= h;

            while (ty < height) {
                g.drawImage(image, x, ty, null);
                ty += h;
            }
        } else {
            g.drawImage(image, x, y, null);
        }
    }

    // non-printing, anti-aliased code from SwingUtilities2, which our build box doesn't like
    public static void drawString(JComponent c, Graphics g, String text, int x, int y) {
        if (text == null || text.length() <= 0) {
            return;
        }
        Graphics2D g2 = (Graphics2D) g;
        Object oldAAValue = g2.getRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING);
        g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        g.drawString(text, x, y);
        g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, oldAAValue);
    }

    public static void paintCandylandBackground(Graphics g, int height, int width, boolean drawGrayBuffer) {
        Graphics2D g2d = (Graphics2D) g.create();

        int h = height;
        if (drawGrayBuffer) h -= GRAY_BUFFER_HEIGHT;

        g2d.setColor(Color.BLACK);
        g2d.drawLine(0, 0, width, 0);
        g2d.drawLine(0, h - 1, width, h - 1);

        g2d.setColor(new Color(130, 130, 128));
        g2d.drawLine(0, 1, width, 1);

        g2d.setColor(new Color(107, 105, 101));
        g2d.drawLine(0, 2, width, 2);

        int midpoint = h / 2;
        int temp_height = midpoint - 2;
        g2d.setPaint(new GradientPaint(0, 3, new Color(78, 78, 77), 0, midpoint, new Color(44, 45, 45)));
        g2d.fillRect(0, 3, width, temp_height);

        g2d.setColor(Color.BLACK);
        g2d.drawLine(0, midpoint + 1, width, midpoint + 1);

        temp_height = h - (midpoint + 4);
        g2d.setPaint(new GradientPaint(0, midpoint + 2, Color.BLACK, 0, midpoint + 2 + temp_height, new Color(44, 44, 44)));
        g2d.fillRect(0, midpoint + 2, width, temp_height);

        g2d.setColor(new Color(30, 30, 30));
        g2d.drawLine(0, h - 2, width, h - 2);

        // optionally draw gray buffer
        if (drawGrayBuffer) {
            g2d.setColor(new Color(79, 79, 79));
            g2d.fillRect(0, h, width, h + 1);
            g2d.setColor(new Color(84, 84, 84));
            g2d.drawLine(0, h + 2, width, h + 2);
            g2d.setColor(new Color(90, 90, 90));
            g2d.drawLine(0, h + 3, width, h + 3);
            g2d.setColor(new Color(58, 58, 58));
            g2d.drawLine(0, h + 4, width, h + 4);
            g2d.setColor(new Color(34, 34, 34));
            g2d.drawLine(0, h + 5, width, h + 5);
        }

        g2d.dispose();

    }
}
